#include "etexturemanager.h"
#include "etexture.h"
#include <SDL_image.h>
#include <SDL_opengl.h>

ETextureManager::ETextureManager()
{
}

int ETextureManager::generateTextureFromSurface(SDL_Surface *pSurface)
{
    GLenum texture_format = GL_RGBA;
    int nNumColors = pSurface->format->BytesPerPixel;

    if (nNumColors == 4)     // contains an alpha channel
    {
        if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
        {
            texture_format = GL_BGRA;
        }
        else
        {
            texture_format = GL_RGBA;
        }
    }
    else if (nNumColors == 3)     // no alpha channel
    {
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
        {
            texture_format = GL_BGR;
        }
        else
        {
            texture_format = GL_RGB;
        }
    }
    else if (nNumColors == 1)
    {
        texture_format = GL_COLOR_INDEX;
    }
    else
    {
       // printf("warning: the image is not truecolor..  this will probably break\n");
        // this error should not go unhandled
        assert(false);
    }

    // OpenGL texture stuff
    unsigned int texID;

    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    // use GL_BGRA to flip Red and Blue channels
    if(nNumColors == 4)
    {
        glTexImage2D( GL_TEXTURE_2D, 0, texture_format, pSurface->w, pSurface->h, 0,
                     texture_format, GL_UNSIGNED_BYTE, pSurface->pixels );
    }
    else if(nNumColors == 3)
    {
        glTexImage2D( GL_TEXTURE_2D, 0, texture_format, pSurface->w, pSurface->h, 0,
                     texture_format, GL_UNSIGNED_BYTE, pSurface->pixels );
    }
    else if(nNumColors == 1)
    {
        glTexImage2D( GL_TEXTURE_2D, 0, 1, pSurface->w, pSurface->h, 0,
                     GL_RED, GL_UNSIGNED_BYTE, pSurface->pixels );
    }

    return texID;
}

boost::shared_ptr<ETexture> ETextureManager::loadTextureFromFile(const std::string &path)
{
    boost::shared_ptr<ETexture> texture;

    // if texture with path already exist
    if(m_textures.find(path) != m_textures.end())
    {
        return texture;
    }

    SDL_Surface* pTexSurface = IMG_Load(path.c_str());
    Q_ASSERT(pTexSurface);

    texture.reset(new ETexture);
    texture->m_nID = generateTextureFromSurface(pTexSurface);
    texture->m_path = path;
    texture->m_nWidth = pTexSurface->w;
    texture->m_nHeight = pTexSurface->h;
    texture->m_nNumColors = pTexSurface->format->BytesPerPixel;
    texture->m_bHasAlpha = (texture->m_nNumColors == 4);

    m_textures[path] = texture;

    return texture;
}

boost::shared_ptr<ETexture> ETextureManager::texture(const std::string &path)
{
    boost::shared_ptr<ETexture> texture;

    if(m_textures.find(path) != m_textures.end())
    {
        texture = m_textures[path];
    }

    return texture;
}
